<template>
  <div style="display:inline-block;margin-left:10px">
    <div :style="{
    width:width+'px'
  }" class="slider">
      <div ref="sl" class="slider-container">
        <div
          :style="{
      position:'absolute',
      left:0,
      top:(sliderHeight-sliderBarHeight)/2+'px',
      height:sliderBarHeight+'px',
      right:0
      }"
          class="track"
        >
          <!-- <div
            v-for="(item,index) in selection.slice(1,-1)"
            :key="index"
            class="mark"
            :style="{
        left:`${(index+1)*(width-40)/(selection.length-1)}px`
      }"
          ></div>-->
          <div
            class="thumb"
            :style="{
          left:currentPos-3+'px',
          transition:trans
        }"
            @mousedown="handleMouseDown"
          ></div>
        </div>
      </div>
      <div class="val">{{value}}</div>
    </div>
    <div style="position:relative">
      <div>{{selection[0]}}</div>
      <div
        style="text-align:right;position:absolute;top:0"
        :style="{
   width:`${width-40}px` 
      }"
      >{{selection[selection.length-1]}}</div>
    </div>
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue, Ref } from "vue-property-decorator";
interface Point {
  x: number;
  y: number;
}

@Component
export default class Slider extends Vue {
  @Prop({ default: 150 })
  private width?: number;
  @Prop({ default: v => v, type: Function })
  private filter: (v: number) => string;
  private realV: number = 0;
  private set value(v) {
    this.realV = v;
  }
  private get value(): string {
    return this.filter(this.realV);
  }
  private sliderHeight: number = 0;
  private sliderBarHeight: number = 10;
  private currentPos: number = 0;
  private lastPos: number = 0;
  private mouseDown: boolean = false;
  private lastMousePos?: Point;
  private trans: string =
    "width 0.3s ease, height 0.3s ease, top 0.3s ease,transform 0.3s ease";
  @Prop({ default: () => [1, 2, 3], type: Array })
  private selection?: Array<number>;
  @Prop({ default: 0, type: Number })
  private initSelection?: number;
  @Ref("sl")
  private sl?: Element;
  private mounted() {
    this.sliderHeight = this.sl!.getBoundingClientRect().height;
    window.addEventListener("mouseleave", this.handleMouseLeave);
    window.addEventListener("mousemove", this.handleMouseMove);
    window.addEventListener("mouseup", this.handleMouseUp);
    this.moveToInt(this.initSelection!);
  }
  private beforeDestroy() {
    window.removeEventListener("mouseleave", this.handleMouseLeave);
    window.removeEventListener("mousemove", this.handleMouseMove);
    window.removeEventListener("mouseup", this.handleMouseUp);
  }
  private handleMouseLeave() {
    this.mouseDown = false;
  }
  private handleMouseDown(e: MouseEvent) {
    this.mouseDown = true;
    this.lastMousePos = {
      x: e.clientX,
      y: e.clientY
    };
  }
  private handleMouseUp(e: MouseEvent) {
    if (this.mouseDown) {
      this.mouseDown = false;
      this.lastPos = this.currentPos;
      const m = Math.round(
        ((this.currentPos) / (this.width! - 48)) *
          (this.selection!.length - 1)
      );
      this.moveToInt(m);
    }
  }
  private handleMouseMove(e: MouseEvent) {
    if (this.mouseDown) {
      this.currentPos = this.lastPos + e.clientX - this.lastMousePos!.x;
      if (this.currentPos < 0) this.currentPos = 0;
      else if (this.currentPos > this.width! - 48)
        this.currentPos = this.width! - 48;
      let num = Math.round(
        ((this.currentPos) / (this.width!-48)) *
          (this.selection!.length - 1)
      );
      if (num < 0) num = 0;
      else if (num > this.selection!.length - 1)
        num = this.selection!.length - 1;
      this.value = this.selection![num];
      this.$emit("value-changed", num);
    }
  }
  private moveToInt(num: number) {
    if (num < 0) num = 0;
    else if (num > this.selection!.length - 1) num = this.selection!.length - 1;
    this.value = this.selection![num];
    this.trans = "all 0.3s ease";
    this.currentPos =
      (num * (this.width! - 48)) / (this.selection!.length - 1);
    this.lastPos = this.currentPos;
    setTimeout(() => {
      this.trans =
        "width 0.3s ease, height 0.3s ease, top 0.3s ease,transform 0.3s ease";
    }, 300);
    this.$emit("value-changed", num);
  }
}
</script>

<style lang="scss" scoped>
.slider {
  user-select: none;
  display: inline-flex;
  height: 30px;
  vertical-align: middle;
  flex-flow: row nowrap;
  .slider-container {
    flex: 1;
    position: relative;
    .track {
      border-radius: 40px;
      border: 1px solid white;
    }
    .thumb {
      display: inline-block;
      position: absolute;
      width: 15px;
      height: 15px;
      top: -3px;
      border-radius: 50%;
      background-color: white;
      border: 1px solid gray;
      cursor: pointer;
    }
    .thumb:hover {
      width: 20px;
      height: 20px;
      top: -5px;
      transform: translateX(-2px);
    }
    .mark {
      display: inline-block;
      position: absolute;
      border-left: solid 2px lightgray;
      top: 3px;
      height: 2px;
    }
  }
  .val {
    flex-basis: 40px;
    text-align: right;
    line-height: 30px;
  }
}
</style>
